<script setup lang="ts">
import { ref, reactive, onMounted, nextTick, computed, watch } from 'vue'
import $icon from '@/utils/iconSheets'

const props = defineProps({
  prepend: {
    type: String,
    default: () => 'ele-Pointer'
  },
  placeholder: {
    type: String,
    default: () => '请输入内容搜索图标或者选择图标'
  },
  type: {
    type: String,
    default: () => 'all'
  },
  // 禁用
  disabled: {
    type: Boolean,
    default: () => false
  },
  // 自定义空状态描述文字
  emptyDescription: {
    type: String,
    default: () => '无相关图标'
  },
  modelValue: String
})

const emit = defineEmits(['update:modelValue', 'get', 'clear'])

const inputWidthRef = ref()
const selectorScrollbarRef = ref()

const state = reactive({
  fontIconPrefix: '',
  fontIconWidth: 0,
  fontIconSearch: '',
  fontIconTabsIndex: 0,
  fontIconSheetsList: [],
  fontIconPlaceholder: '',
  fontIconType: 'ali',
  fontIconShow: true,
  list: [
    {
      label: 'ali',
      value: 'ali'
    },
    {
      label: 'ele',
      value: 'ele'
    },
    {
      label: 'awe',
      value: 'awe'
    },
    {
      label: 'remix',
      value: 'remix'
    }
  ]
})

const onIconFocus = () => {
  if (!props.modelValue) return false
  state.fontIconSearch = ''
  state.fontIconPlaceholder = props.modelValue
}
// 处理 input 失去焦点时，为空将清空 input 值，为点击选中图标时，将取原先值
const onIconBlur = () => {
  setTimeout(() => {
    const icon = state.fontIconSheetsList.filter(
      (icon: string) => icon === state.fontIconSearch
    )
    if (icon.length <= 0) state.fontIconSearch = ''
  }, 300)
}

const initModeValueEcho = () => {
  if (props.modelValue === '') {
    return ((<string | undefined>state.fontIconPlaceholder) = props.placeholder)
  }
  (<string | undefined>state.fontIconPlaceholder) = props.modelValue
  ;(<string | undefined>state.fontIconPrefix) = props.modelValue
}

const initFontIconTypeEcho = () => {
  if (props.modelValue!.indexOf('iconfont') > -1) onIconChange('ali')
  else if (props.modelValue!.indexOf('ele-') > -1) onIconChange('ele')
  else if (props.modelValue!.indexOf('fa') > -1) onIconChange('awe')
  else onIconChange('ali')
}

const onIconChange = (type: string) => {
  state.fontIconType = type
  initFontIconData(type)
}

const initFontIconData = async (type: string) => {
  state.fontIconSheetsList = []
  if (type === 'ali') {
    await $icon.getAlicdnIconfont().then((res: any) => {
      state.fontIconSheetsList = res.map((i: string) => `iconfont ${i}`)
    })
  } else if (type === 'ele') {
    await $icon.getElementPlusIconfont().then((res: any) => {
      state.fontIconSheetsList = res.map((i: string) => `ele-${i}`)
    })
  } else if (type === 'awe') {
    await $icon.getAwesomeIconfont().then((res: any) => {
      state.fontIconSheetsList = res.map((i: string) => `fa ${i}`)
    })
  } else if (type === 'remix') {
    await $icon.getRemixIconfont().then((res: any) => {
      state.fontIconSheetsList = res.map((i: string) => `${i}`)
    })
  }
  state.fontIconPlaceholder = props.placeholder
  initModeValueEcho()
}

const onPopoverShow = () => {
  initModeValueEcho()
  initFontIconTypeEcho()
}

const initResize = () => {
  window.addEventListener('resize', () => {
    getInputWidth()
  })
}

const getInputWidth = () => {
  nextTick(() => {
    state.fontIconWidth = inputWidthRef.value.$el.offsetWidth
  })
}

const fontIconSheetsFilterList = computed(() => {
  if (!state.fontIconSearch) return state.fontIconSheetsList
  const search = state.fontIconSearch.trim().toLowerCase()
  return state.fontIconSheetsList.filter((item: string) => {
    if (item.toLowerCase().indexOf(search) !== -1) return item
  })
})

const onColClick = (v: string) => {
  state.fontIconPlaceholder = v
  state.fontIconPrefix = v
  emit('update:modelValue', state.fontIconPrefix)
}

onMounted(() => {
  initModeValueEcho()
  initResize()
  getInputWidth()
})

watch(
  () => props.modelValue,
  () => {
    initModeValueEcho()
  }
)

watch(
  () => state.fontIconType,
  (e: string) => {
    onIconChange(e)
  }
)
</script>

<template>
  <div class="w-full h-full">
    <el-popover
      placement="bottom"
      trigger="click"
      transition="el-zoom-in-top"
      popper-class="icon-selector-popper"
      :width="state.fontIconWidth"
      @show="onPopoverShow"
    >
      <template #reference>
        <el-input
          ref="inputWidthRef"
          v-model="state.fontIconSearch"
          :placeholder="state.fontIconPlaceholder"
          :clearable="true"
          :disabled="disabled"
          @focus="onIconFocus"
          @blur="onIconBlur"
        >
          <template #prepend>
            <svg-icon :name="state.fontIconPrefix || prepend" :size="16" />
          </template>
        </el-input>
      </template>
      <template #default>
        <div class="icon-selector-warp">
          <tabs
            class="mb-2"
            v-model="state.fontIconType"
            :list="state.list"
            v-if="type === 'all'"
          />
          <div class="icon-selector-warp-row">
            <el-scrollbar class="overflow-hidden" ref="selectorScrollbarRef">
              <el-row :gutter="5" v-if="fontIconSheetsFilterList.length > 0">
                <el-col
                  :xs="2"
                  :sm="2"
                  :md="2"
                  :lg="1"
                  :xl="1"
                  @click="onColClick(v)"
                  v-for="(v, k) in fontIconSheetsFilterList"
                  :key="k"
                >
                  <div
                    class="icon-selector-warp-item"
                    :class="{
                      'icon-selector-active': state.fontIconPrefix === v
                    }"
                  >
                    <svg-icon
                      class="text-xl"
                      :class="
                        state.fontIconPrefix === v
                          ? 'text-blue-300'
                          : 'text-gray-400'
                      "
                      :name="v"
                    />
                  </div>
                </el-col>
              </el-row>
              <el-empty
                :image-size="100"
                v-if="fontIconSheetsFilterList.length <= 0"
                :description="emptyDescription"
              />
            </el-scrollbar>
          </div>
        </div>
      </template>
    </el-popover>
  </div>
</template>

<style lang="scss" scoped>
.icon-selector-warp {
  @apply h-[300px] overflow-hidden;

  .icon-selector-warp-row {
    @apply h-[250px] overflow-hidden;
    :deep(.el-scrollbar__bar.is-horizontal) {
      display: none !important;
      height: 0 !important;
    }
    .icon-selector-warp-item {
      @apply flex items-center justify-center p-2 mb-1 rounded-md border border-solid border-light-800 cursor-pointer hover:(bg-blue-50 border border-solid border-blue-100);
    }
    .icon-selector-active {
      @apply bg-blue-50 border border-solid border-blue-100;
    }
  }
}
</style>
